using UnityEngine;

public static class ImageMergerUtil
{
    #region  bg blender fg 

    /// <summary>
    /// 将两张图合成为一张（背景在下，前景在上，自动比例缩放、居中、无越界）
    /// </summary>
    public static Texture2D MergeTextures(Texture2D bgTex, Texture2D fgTex, int featherSize = 10)
    {
        if (bgTex == null || fgTex == null)
        {
            Debug.LogError("MergeTextures 参数为空！");
            return null;
        }

        // 取最大尺寸作为结果输出
        int resultW = Mathf.Max(bgTex.width, fgTex.width);
        int resultH = Mathf.Max(bgTex.height, fgTex.height);
        Texture2D result = new Texture2D(resultW, resultH, TextureFormat.RGBA32, false);

        // 填充底色（白色，可改成 Color.clear）
        Color[] fill = new Color[resultW * resultH];
        for (int i = 0; i < fill.Length; i++) fill[i] = Color.white;
        result.SetPixels(fill);

        // 自动判断：如果背景比结果小，就放大覆盖，否则按比例居中
        Texture2D scaledBg = (bgTex.width < resultW || bgTex.height < resultH)
            ? ScaleToCover(bgTex, resultW, resultH)
            : ScaleToFit(bgTex, resultW, resultH);

        // 前景一般保持完整显示（按比例 fit）
        Texture2D scaledFg = ScaleToFit(fgTex, resultW, resultH);

        // 坐标居中
        int bgX = (resultW - scaledBg.width) / 2;
        int bgY = (resultH - scaledBg.height) / 2;
        int fgX = (resultW - scaledFg.width) / 2;
        int fgY = (resultH - scaledFg.height) / 2;

        // 安全地绘制背景
        BlitToResultSafe(result, scaledBg, bgX, bgY);

        // 混合前景（带透明与羽化）
        SafeBlendForeground(result, scaledFg, fgX, fgY, featherSize);

        result.Apply();
        return result;
    }

    // -------------------- 核心函数 --------------------

    /// <summary>安全绘制，避免超出 result 边界</summary>
    private static void BlitToResultSafe(Texture2D result, Texture2D src, int dstX, int dstY)
    {
        int srcStartX = 0;
        int srcStartY = 0;
        int srcW = src.width;
        int srcH = src.height;

        int dstStartX = dstX;
        int dstStartY = dstY;
        int dstW = srcW;
        int dstH = srcH;

        if (dstStartX < 0)
        {
            srcStartX = -dstStartX;
            dstW -= srcStartX;
            dstStartX = 0;
        }
        if (dstStartY < 0)
        {
            srcStartY = -dstStartY;
            dstH -= srcStartY;
            dstStartY = 0;
        }

        if (dstStartX + dstW > result.width)
            dstW = result.width - dstStartX;
        if (dstStartY + dstH > result.height)
            dstH = result.height - dstStartY;

        if (srcStartX + dstW > src.width)
            dstW = src.width - srcStartX;
        if (srcStartY + dstH > src.height)
            dstH = src.height - srcStartY;

        if (dstW <= 0 || dstH <= 0) return;

        Color[] pixels = src.GetPixels(srcStartX, srcStartY, dstW, dstH);
        result.SetPixels(dstStartX, dstStartY, dstW, dstH, pixels);
    }

    /// <summary>混合前景图（透明 + 羽化 + 无越界）</summary>
    private static void SafeBlendForeground(Texture2D result, Texture2D fg, int dstX, int dstY, int featherSize)
    {
        int srcStartX = 0;
        int srcStartY = 0;
        int srcW = fg.width;
        int srcH = fg.height;

        int dstStartX = dstX;
        int dstStartY = dstY;
        int dstW = srcW;
        int dstH = srcH;

        if (dstStartX < 0)
        {
            srcStartX = -dstStartX;
            dstW -= srcStartX;
            dstStartX = 0;
        }
        if (dstStartY < 0)
        {
            srcStartY = -dstStartY;
            dstH -= srcStartY;
            dstStartY = 0;
        }

        if (dstStartX + dstW > result.width)
            dstW = result.width - dstStartX;
        if (dstStartY + dstH > result.height)
            dstH = result.height - dstStartY;

        if (srcStartX + dstW > fg.width)
            dstW = fg.width - srcStartX;
        if (srcStartY + dstH > fg.height)
            dstH = fg.height - srcStartY;

        if (dstW <= 0 || dstH <= 0) return;

        Color[] fgPixels = fg.GetPixels(srcStartX, srcStartY, dstW, dstH);
        Color[] bgPixels = result.GetPixels(dstStartX, dstStartY, dstW, dstH);

        for (int i = 0; i < fgPixels.Length; i++)
        {
            int x = i % dstW;
            int y = i / dstW;
            Color fgC = fgPixels[i];
            Color bgC = bgPixels[i];

            if (featherSize > 0)
            {
                int globalX = srcStartX + x;
                int globalY = srcStartY + y;
                float distToEdge = Mathf.Min(
                    Mathf.Min(globalX, fg.width - 1 - globalX),
                    Mathf.Min(globalY, fg.height - 1 - globalY)
                );
                float fade = Mathf.Clamp01(distToEdge / featherSize);
                fgC.a *= fade;
            }

            float a = fgC.a;
            Color blended = new Color(
                fgC.r * a + bgC.r * (1 - a),
                fgC.g * a + bgC.g * (1 - a),
                fgC.b * a + bgC.b * (1 - a),
                1f
            );
            bgPixels[i] = blended;
        }

        result.SetPixels(dstStartX, dstStartY, dstW, dstH, bgPixels);
    }

    // -------------------- 缩放 --------------------
    private static Texture2D ScaleToFit(Texture2D src, int targetW, int targetH)
    {
        float ratio = Mathf.Min((float)targetW / src.width, (float)targetH / src.height);
        int newW = Mathf.Max(1, Mathf.RoundToInt(src.width * ratio));
        int newH = Mathf.Max(1, Mathf.RoundToInt(src.height * ratio));
        return ScaleTexture(src, newW, newH);
    }

    private static Texture2D ScaleToCover(Texture2D src, int targetW, int targetH)
    {
        float ratio = Mathf.Max((float)targetW / src.width, (float)targetH / src.height);
        int newW = Mathf.Max(1, Mathf.RoundToInt(src.width * ratio));
        int newH = Mathf.Max(1, Mathf.RoundToInt(src.height * ratio));
        return ScaleTexture(src, newW, newH);
    }

    private static Texture2D ScaleTexture(Texture2D src, int newW, int newH)
    {
        RenderTexture rt = RenderTexture.GetTemporary(newW, newH, 0, RenderTextureFormat.ARGB32);
        Graphics.Blit(src, rt);
        Texture2D tex = new Texture2D(newW, newH, TextureFormat.RGBA32, false);
        RenderTexture.active = rt;
        tex.ReadPixels(new Rect(0, 0, newW, newH), 0, 0);
        tex.Apply();
        RenderTexture.active = null;
        RenderTexture.ReleaseTemporary(rt);
        return tex;
    }


    #endregion

    #region frame image add to photo 

    /// <summary>
    /// 将边框贴到背景图上（边框居中对齐、带透明区域）
    /// </summary>
    public static Texture2D AddFrame(Texture2D bgTex, Texture2D frameTex)
    {
        if (bgTex == null || frameTex == null)
        {
            Debug.LogError("AddFrame 参数为空！");
            return null;
        }

        int resultW = bgTex.width;
        int resultH = bgTex.height;
        Texture2D result = new Texture2D(resultW, resultH, TextureFormat.RGBA32, false);

        // 拷贝背景图
        result.SetPixels(bgTex.GetPixels());

        // 缩放边框到背景大小（保持比例或强制铺满都可以）
        Texture2D scaledFrame = ScaleTexture2(frameTex, resultW, resultH);

        // 前景叠加（带透明度）
        Color[] bgPixels = result.GetPixels();
        Color[] framePixels = scaledFrame.GetPixels();

        for (int i = 0; i < bgPixels.Length; i++)
        {
            Color bg = bgPixels[i];
            Color frame = framePixels[i];

            float a = frame.a;
            bgPixels[i] = new Color(
                frame.r * a + bg.r * (1 - a),
                frame.g * a + bg.g * (1 - a),
                frame.b * a + bg.b * (1 - a),
                1f
            );
        }

        result.SetPixels(bgPixels);
        result.Apply();

        return result;
    }

    /// <summary>缩放贴图到指定大小</summary>
    private static Texture2D ScaleTexture2(Texture2D src, int width, int height)
    {
        RenderTexture rt = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.ARGB32);
        Graphics.Blit(src, rt);
        Texture2D tex = new Texture2D(width, height, TextureFormat.RGBA32, false);
        RenderTexture.active = rt;
        tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
        tex.Apply();
        RenderTexture.active = null;
        RenderTexture.ReleaseTemporary(rt);
        return tex;
    }

    #endregion

    #region signature image add  white bg

    public static Texture2D FillWithWhite(Texture2D src)
    {
        int w = src.width;
        int h = src.height;
        Texture2D result = new Texture2D(w, h, TextureFormat.RGBA32, false);

        Color[] pixels = src.GetPixels();
        for (int i = 0; i < pixels.Length; i++)
        {
            Color c = pixels[i];
            // 白底混合：前景*(alpha) + 白色*(1-alpha)
            c.r = c.r * c.a + 1f * (1f - c.a);
            c.g = c.g * c.a + 1f * (1f - c.a);
            c.b = c.b * c.a + 1f * (1f - c.a);
            c.a = 1f; // 结果完全不透明
            pixels[i] = c;
        }

        result.SetPixels(pixels);
        result.Apply();
        return result;
    }


    #endregion

    #region signature image normalized , add to photo 
      
    /// <summary>
    /// 将签名贴到照片的指定归一化区域
    /// </summary>
    /// <param name="photo">原图 Texture2D</param>
    /// <param name="signature">签名 Texture2D</param>
    /// <param name="bottomLeft">归一化左下角 (0~1)</param>
    /// <param name="topRight">归一化右上角 (0~1)</param>
    public static Texture2D ApplySignature(Texture2D photo, Texture2D signature, Vector2 bottomLeft, Vector2 topRight)
    {
        int startX = Mathf.RoundToInt(bottomLeft.x * photo.width);
        int startY = Mathf.RoundToInt(bottomLeft.y * photo.height);
        int endX = Mathf.RoundToInt(topRight.x * photo.width);
        int endY = Mathf.RoundToInt(topRight.y * photo.height);

        int targetWidth = endX - startX;
        int targetHeight = endY - startY;

        for (int y = 0; y < targetHeight; y++)
        {
            for (int x = 0; x < targetWidth; x++)
            {
                // 从签名图按比例取像素
                int sigX = Mathf.RoundToInt((float)x / targetWidth * signature.width);
                int sigY = Mathf.RoundToInt((float)y / targetHeight * signature.height);

                Color sigColor = signature.GetPixel(sigX, sigY);

                // 如果签名有透明背景，就混合到照片上
                Color photoColor = photo.GetPixel(startX + x, startY + y);
                Color blended = Color.Lerp(photoColor, sigColor, sigColor.a);
                photo.SetPixel(startX + x, startY + y, blended);
            }
        }

        photo.Apply();
        return photo;
    }

    #endregion
}
